﻿/* 
* Copyright (c) 2010, The University of Texas at Austin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation and/or other materials 
* provided with the distribution.
*
* Neither the name of The University of Texas at Austin nor the names of its contributors may be 
* used to endorse or promote products derived from this software without specific prior written 
* permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;

namespace Bio.Views.Structure.Editor.Internal.Rendering.Visuals
{
    public class BasePairDrawingVisual : DrawingVisual
    {
        public Rect Measure()
        {
            double localConnectorSize = Container.BasePairConnectorSize.Value;
            if (localConnectorSize > Container.Magnitude || localConnectorSize <= 0)
                localConnectorSize = Container.Magnitude; //Pickup the magnitude if the size is not "valid"
            
            if (Container.BasePairConnectorRenderingStyle == BasePairConnectorRenderingMode.Circle)
            {
                EllipseGeometry circleGeometry = new EllipseGeometry();
                circleGeometry.Center = Container.Location;
                circleGeometry.RadiusX = (Math.Round(localConnectorSize / 2.0));
                circleGeometry.RadiusY = circleGeometry.RadiusX;
                CurrentConnectorRenderingGeometry = circleGeometry;
            }
            else if (Container.BasePairConnectorRenderingStyle == BasePairConnectorRenderingMode.Line)
            {
                LineGeometry lineGeometry = new LineGeometry();
                double centerToEdgeDist = Math.Round(localConnectorSize / 2.0);
                double startx = Container.Location.X - (centerToEdgeDist * Math.Cos(Container.RayAngle));
                double starty = Container.Location.Y - (centerToEdgeDist * Math.Sin(Container.RayAngle));
                double endx = startx + localConnectorSize * Math.Cos(Container.RayAngle);
                double endy = starty + localConnectorSize * Math.Sin(Container.RayAngle);
                lineGeometry.StartPoint = new Point(startx, starty);
                lineGeometry.EndPoint = new Point(endx, endy);
                CurrentConnectorRenderingGeometry = lineGeometry;
            }
            else //Has to be Rectangle rendering mode.
            {
                RectangleGeometry rectGeometry = new RectangleGeometry();
                double topLeftX = Container.Location.X - (Math.Round(localConnectorSize / 2.0));
                double topLeftY = Container.Location.Y - (Math.Round(localConnectorSize / 2.0));
                rectGeometry.Rect = new Rect(topLeftX, topLeftY, localConnectorSize, localConnectorSize);
                rectGeometry.Transform = new RotateTransform(Container.RayAngle * (180.0 / Math.PI), Container.Location.X, Container.Location.Y);
                CurrentConnectorRenderingGeometry = rectGeometry;
            }
            return CurrentConnectorRenderingGeometry.Bounds;
        }

        public void Render()
        {
            using (var drawingContext = RenderOpen())
            {
                if (Container.IsComponentVisible)
                {
                    if (Container.BasePairConnectorIsVisible.Value)
                    {
                        if (Container.BasePairConnectorRenderingStyle == BasePairConnectorRenderingMode.Line)
                        {
                            drawingContext.DrawGeometry(null, new Pen(Container.BasePairConnectorStroke, Container.BasePairConnectorStrokeThickness.Value), CurrentConnectorRenderingGeometry);
                        }
                        else if (Container.BasePairConnectorIsFilled.Value)
                        {
                            drawingContext.DrawGeometry(Container.BasePairConnectorFill, new Pen(Container.BasePairConnectorStroke, Container.BasePairConnectorStrokeThickness.Value), CurrentConnectorRenderingGeometry);
                        }
                        else
                        {
                            drawingContext.DrawGeometry(null, new Pen(Container.BasePairConnectorStroke, Container.BasePairConnectorStrokeThickness.Value), CurrentConnectorRenderingGeometry);
                        }
                    }
                }
            }
        }

        public BasePairDrawingVisual(BasePairStructureElementVisualComponent container)
        {
            Debug.Assert(container != null);
            Container = container;
        }

        private BasePairStructureElementVisualComponent Container { get; set; }
        private Geometry CurrentConnectorRenderingGeometry { get; set; }
    }
}
